/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/* JOrbis
 * Copyright (C) 2000 ymnk, JCraft,Inc.
 *  
 * Written by: 2000 ymnk<ymnk@jcraft.com>
 *   
 * Many thanks to 
 *   Monty <monty@xiph.org> and 
 *   The XIPHOPHORUS Company http://www.xiph.org/ .
 * JOrbis has been based on their awesome works, Vorbis codec.
 *   
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public License
 * as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
   
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package com.jcraft.jorbis;

class Drft{
  int n;
  float[] trigcache;
  int[] splitcache;

  void backward(float[] data){
    if(n==1)
      return;
    drftb1(n, data, trigcache, trigcache, n, splitcache);
  }

  void init(int n){
    this.n=n;
    trigcache=new float[3*n];
    splitcache=new int[32];
    fdrffti(n, trigcache, splitcache);
  }

  void clear(){
    if(trigcache!=null)
      trigcache=null;
    if(splitcache!=null)
      splitcache=null;
  }

  static int[] ntryh= {4, 2, 3, 5};
  static float tpi=6.28318530717958647692528676655900577f;
  static float hsqt2=.70710678118654752440084436210485f;
  static float taui=.86602540378443864676372317075293618f;
  static float taur=-.5f;
  static float sqrt2=1.4142135623730950488016887242097f;

  static void drfti1(int n, float[] wa, int index, int[] ifac){
    float arg, argh, argld, fi;
    int ntry=0, i, j=-1;
    int k1, l1, l2, ib;
    int ld, ii, ip, is, nq, nr;
    int ido, ipm, nfm1;
    int nl=n;
    int nf=0;

    int state=101;

    loop: while(true){
      switch(state){
        case 101:
          j++;
          if(j<4)
            ntry=ntryh[j];
          else
            ntry+=2;
        case 104:
          nq=nl/ntry;
          nr=nl-ntry*nq;
          if(nr!=0){
            state=101;
            break;
          }
          nf++;
          ifac[nf+1]=ntry;
          nl=nq;
          if(ntry!=2){
            state=107;
            break;
          }
          if(nf==1){
            state=107;
            break;
          }

          for(i=1; i<nf; i++){
            ib=nf-i+1;
            ifac[ib+1]=ifac[ib];
          }
          ifac[2]=2;
        case 107:
          if(nl!=1){
            state=104;
            break;
          }
          ifac[0]=n;
          ifac[1]=nf;
          argh=tpi/n;
          is=0;
          nfm1=nf-1;
          l1=1;

          if(nfm1==0)
            return;

          for(k1=0; k1<nfm1; k1++){
            ip=ifac[k1+2];
            ld=0;
            l2=l1*ip;
            ido=n/l2;
            ipm=ip-1;

            for(j=0; j<ipm; j++){
              ld+=l1;
              i=is;
              argld=(float)ld*argh;
              fi=0.f;
              for(ii=2; ii<ido; ii+=2){
                fi+=1.f;
                arg=fi*argld;
                wa[index+i++]=(float)Math.cos(arg);
                wa[index+i++]=(float)Math.sin(arg);
              }
              is+=ido;
            }
            l1=l2;
          }
          break loop;
      }
    }
  }

  static void fdrffti(int n, float[] wsave, int[] ifac){
    if(n==1)
      return;
    drfti1(n, wsave, n, ifac);
  }

  static void dradf2(int ido, int l1, float[] cc, float[] ch, float[] wa1,
      int index){
    int i, k;
    float ti2, tr2;
    int t0, t1, t2, t3, t4, t5, t6;

    t1=0;
    t0=(t2=l1*ido);
    t3=ido<<1;
    for(k=0; k<l1; k++){
      ch[t1<<1]=cc[t1]+cc[t2];
      ch[(t1<<1)+t3-1]=cc[t1]-cc[t2];
      t1+=ido;
      t2+=ido;
    }

    if(ido<2)
      return;

    if(ido!=2){
      t1=0;
      t2=t0;
      for(k=0; k<l1; k++){
        t3=t2;
        t4=(t1<<1)+(ido<<1);
        t5=t1;
        t6=t1+t1;
        for(i=2; i<ido; i+=2){
          t3+=2;
          t4-=2;
          t5+=2;
          t6+=2;
          tr2=wa1[index+i-2]*cc[t3-1]+wa1[index+i-1]*cc[t3];
          ti2=wa1[index+i-2]*cc[t3]-wa1[index+i-1]*cc[t3-1];
          ch[t6]=cc[t5]+ti2;
          ch[t4]=ti2-cc[t5];
          ch[t6-1]=cc[t5-1]+tr2;
          ch[t4-1]=cc[t5-1]-tr2;
        }
        t1+=ido;
        t2+=ido;
      }
      if(ido%2==1)
        return;
    }

    t3=(t2=(t1=ido)-1);
    t2+=t0;
    for(k=0; k<l1; k++){
      ch[t1]=-cc[t2];
      ch[t1-1]=cc[t3];
      t1+=ido<<1;
      t2+=ido;
      t3+=ido;
    }
  }

  static void dradf4(int ido, int l1, float[] cc, float[] ch, float[] wa1,
      int index1, float[] wa2, int index2, float[] wa3, int index3){
    int i, k, t0, t1, t2, t3, t4, t5, t6;
    float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
    t0=l1*ido;

    t1=t0;
    t4=t1<<1;
    t2=t1+(t1<<1);
    t3=0;

    for(k=0; k<l1; k++){
      tr1=cc[t1]+cc[t2];
      tr2=cc[t3]+cc[t4];

      ch[t5=t3<<2]=tr1+tr2;
      ch[(ido<<2)+t5-1]=tr2-tr1;
      ch[(t5+=(ido<<1))-1]=cc[t3]-cc[t4];
      ch[t5]=cc[t2]-cc[t1];

      t1+=ido;
      t2+=ido;
      t3+=ido;
      t4+=ido;
    }
    if(ido<2)
      return;

    if(ido!=2){
      t1=0;
      for(k=0; k<l1; k++){
        t2=t1;
        t4=t1<<2;
        t5=(t6=ido<<1)+t4;
        for(i=2; i<ido; i+=2){
          t3=(t2+=2);
          t4+=2;
          t5-=2;

          t3+=t0;
          cr2=wa1[index1+i-2]*cc[t3-1]+wa1[index1+i-1]*cc[t3];
          ci2=wa1[index1+i-2]*cc[t3]-wa1[index1+i-1]*cc[t3-1];
          t3+=t0;
          cr3=wa2[index2+i-2]*cc[t3-1]+wa2[index2+i-1]*cc[t3];
          ci3=wa2[index2+i-2]*cc[t3]-wa2[index2+i-1]*cc[t3-1];
          t3+=t0;
          cr4=wa3[index3+i-2]*cc[t3-1]+wa3[index3+i-1]*cc[t3];
          ci4=wa3[index3+i-2]*cc[t3]-wa3[index3+i-1]*cc[t3-1];

          tr1=cr2+cr4;
          tr4=cr4-cr2;
          ti1=ci2+ci4;
          ti4=ci2-ci4;

          ti2=cc[t2]+ci3;
          ti3=cc[t2]-ci3;
          tr2=cc[t2-1]+cr3;
          tr3=cc[t2-1]-cr3;

          ch[t4-1]=tr1+tr2;
          ch[t4]=ti1+ti2;

          ch[t5-1]=tr3-ti4;
          ch[t5]=tr4-ti3;

          ch[t4+t6-1]=ti4+tr3;
          ch[t4+t6]=tr4+ti3;

          ch[t5+t6-1]=tr2-tr1;
          ch[t5+t6]=ti1-ti2;
        }
        t1+=ido;
      }
      if((ido&1)!=0)
        return;
    }

    t2=(t1=t0+ido-1)+(t0<<1);
    t3=ido<<2;
    t4=ido;
    t5=ido<<1;
    t6=ido;

    for(k=0; k<l1; k++){
      ti1=-hsqt2*(cc[t1]+cc[t2]);
      tr1=hsqt2*(cc[t1]-cc[t2]);

      ch[t4-1]=tr1+cc[t6-1];
      ch[t4+t5-1]=cc[t6-1]-tr1;

      ch[t4]=ti1-cc[t1+t0];
      ch[t4+t5]=ti1+cc[t1+t0];

      t1+=ido;
      t2+=ido;
      t4+=t3;
      t6+=ido;
    }
  }

  static void dradfg(int ido, int ip, int l1, int idl1, float[] cc, float[] c1,
      float[] c2, float[] ch, float[] ch2, float[] wa, int index){
    int idij, ipph, i, j, k, l, ic, ik, is;
    int t0, t1, t2=0, t3, t4, t5, t6, t7, t8, t9, t10;
    float dc2, ai1, ai2, ar1, ar2, ds2;
    int nbd;
    float dcp=0, arg, dsp=0, ar1h, ar2h;
    int idp2, ipp2;

    arg=tpi/(float)ip;
    dcp=(float)Math.cos(arg);
    dsp=(float)Math.sin(arg);
    ipph=(ip+1)>>1;
    ipp2=ip;
    idp2=ido;
    nbd=(ido-1)>>1;
    t0=l1*ido;
    t10=ip*ido;

    int state=100;
    loop: while(true){
      switch(state){
        case 101:
          if(ido==1){
            state=119;
            break;
          }
          for(ik=0; ik<idl1; ik++)
            ch2[ik]=c2[ik];

          t1=0;
          for(j=1; j<ip; j++){
            t1+=t0;
            t2=t1;
            for(k=0; k<l1; k++){
              ch[t2]=c1[t2];
              t2+=ido;
            }
          }

          is=-ido;
          t1=0;
          if(nbd>l1){
            for(j=1; j<ip; j++){
              t1+=t0;
              is+=ido;
              t2=-ido+t1;
              for(k=0; k<l1; k++){
                idij=is-1;
                t2+=ido;
                t3=t2;
                for(i=2; i<ido; i+=2){
                  idij+=2;
                  t3+=2;
                  ch[t3-1]=wa[index+idij-1]*c1[t3-1]+wa[index+idij]*c1[t3];
                  ch[t3]=wa[index+idij-1]*c1[t3]-wa[index+idij]*c1[t3-1];
                }
              }
            }
          }
          else{

            for(j=1; j<ip; j++){
              is+=ido;
              idij=is-1;
              t1+=t0;
              t2=t1;
              for(i=2; i<ido; i+=2){
                idij+=2;
                t2+=2;
                t3=t2;
                for(k=0; k<l1; k++){
                  ch[t3-1]=wa[index+idij-1]*c1[t3-1]+wa[index+idij]*c1[t3];
                  ch[t3]=wa[index+idij-1]*c1[t3]-wa[index+idij]*c1[t3-1];
                  t3+=ido;
                }
              }
            }
          }

          t1=0;
          t2=ipp2*t0;
          if(nbd<l1){
            for(j=1; j<ipph; j++){
              t1+=t0;
              t2-=t0;
              t3=t1;
              t4=t2;
              for(i=2; i<ido; i+=2){
                t3+=2;
                t4+=2;
                t5=t3-ido;
                t6=t4-ido;
                for(k=0; k<l1; k++){
                  t5+=ido;
                  t6+=ido;
                  c1[t5-1]=ch[t5-1]+ch[t6-1];
                  c1[t6-1]=ch[t5]-ch[t6];
                  c1[t5]=ch[t5]+ch[t6];
                  c1[t6]=ch[t6-1]-ch[t5-1];
                }
              }
            }
          }
          else{
            for(j=1; j<ipph; j++){
              t1+=t0;
              t2-=t0;
              t3=t1;
              t4=t2;
              for(k=0; k<l1; k++){
                t5=t3;
                t6=t4;
                for(i=2; i<ido; i+=2){
                  t5+=2;
                  t6+=2;
                  c1[t5-1]=ch[t5-1]+ch[t6-1];
                  c1[t6-1]=ch[t5]-ch[t6];
                  c1[t5]=ch[t5]+ch[t6];
                  c1[t6]=ch[t6-1]-ch[t5-1];
                }
                t3+=ido;
                t4+=ido;
              }
            }
          }
        case 119:
          for(ik=0; ik<idl1; ik++)
            c2[ik]=ch2[ik];

          t1=0;
          t2=ipp2*idl1;
          for(j=1; j<ipph; j++){
            t1+=t0;
            t2-=t0;
            t3=t1-ido;
            t4=t2-ido;
            for(k=0; k<l1; k++){
              t3+=ido;
              t4+=ido;
              c1[t3]=ch[t3]+ch[t4];
              c1[t4]=ch[t4]-ch[t3];
            }
          }

          ar1=1.f;
          ai1=0.f;
          t1=0;
          t2=ipp2*idl1;
          t3=(ip-1)*idl1;
          for(l=1; l<ipph; l++){
            t1+=idl1;
            t2-=idl1;
            ar1h=dcp*ar1-dsp*ai1;
            ai1=dcp*ai1+dsp*ar1;
            ar1=ar1h;
            t4=t1;
            t5=t2;
            t6=t3;
            t7=idl1;

            for(ik=0; ik<idl1; ik++){
              ch2[t4++]=c2[ik]+ar1*c2[t7++];
              ch2[t5++]=ai1*c2[t6++];
            }

            dc2=ar1;
            ds2=ai1;
            ar2=ar1;
            ai2=ai1;

            t4=idl1;
            t5=(ipp2-1)*idl1;
            for(j=2; j<ipph; j++){
              t4+=idl1;
              t5-=idl1;

              ar2h=dc2*ar2-ds2*ai2;
              ai2=dc2*ai2+ds2*ar2;
              ar2=ar2h;

              t6=t1;
              t7=t2;
              t8=t4;
              t9=t5;
              for(ik=0; ik<idl1; ik++){
                ch2[t6++]+=ar2*c2[t8++];
                ch2[t7++]+=ai2*c2[t9++];
              }
            }
          }
          t1=0;
          for(j=1; j<ipph; j++){
            t1+=idl1;
            t2=t1;
            for(ik=0; ik<idl1; ik++)
              ch2[ik]+=c2[t2++];
          }

          if(ido<l1){
            state=132;
            break;
          }

          t1=0;
          t2=0;
          for(k=0; k<l1; k++){
            t3=t1;
            t4=t2;
            for(i=0; i<ido; i++)
              cc[t4++]=ch[t3++];
            t1+=ido;
            t2+=t10;
          }
          state=135;
          break;

        case 132:
          for(i=0; i<ido; i++){
            t1=i;
            t2=i;
            for(k=0; k<l1; k++){
              cc[t2]=ch[t1];
              t1+=ido;
              t2+=t10;
            }
          }
        case 135:
          t1=0;
          t2=ido<<1;
          t3=0;
          t4=ipp2*t0;
          for(j=1; j<ipph; j++){
            t1+=t2;
            t3+=t0;
            t4-=t0;

            t5=t1;
            t6=t3;
            t7=t4;

            for(k=0; k<l1; k++){
              cc[t5-1]=ch[t6];
              cc[t5]=ch[t7];
              t5+=t10;
              t6+=ido;
              t7+=ido;
            }
          }

          if(ido==1)
            return;
          if(nbd<l1){
            state=141;
            break;
          }

          t1=-ido;
          t3=0;
          t4=0;
          t5=ipp2*t0;
          for(j=1; j<ipph; j++){
            t1+=t2;
            t3+=t2;
            t4+=t0;
            t5-=t0;
            t6=t1;
            t7=t3;
            t8=t4;
            t9=t5;
            for(k=0; k<l1; k++){
              for(i=2; i<ido; i+=2){
                ic=idp2-i;
                cc[i+t7-1]=ch[i+t8-1]+ch[i+t9-1];
                cc[ic+t6-1]=ch[i+t8-1]-ch[i+t9-1];
                cc[i+t7]=ch[i+t8]+ch[i+t9];
                cc[ic+t6]=ch[i+t9]-ch[i+t8];
              }
              t6+=t10;
              t7+=t10;
              t8+=ido;
              t9+=ido;
            }
          }
          return;
        case 141:
          t1=-ido;
          t3=0;
          t4=0;
          t5=ipp2*t0;
          for(j=1; j<ipph; j++){
            t1+=t2;
            t3+=t2;
            t4+=t0;
            t5-=t0;
            for(i=2; i<ido; i+=2){
              t6=idp2+t1-i;
              t7=i+t3;
              t8=i+t4;
              t9=i+t5;
              for(k=0; k<l1; k++){
                cc[t7-1]=ch[t8-1]+ch[t9-1];
                cc[t6-1]=ch[t8-1]-ch[t9-1];
                cc[t7]=ch[t8]+ch[t9];
                cc[t6]=ch[t9]-ch[t8];
                t6+=t10;
                t7+=t10;
                t8+=ido;
                t9+=ido;
              }
            }
          }
          break loop;
      }
    }
  }

  static void drftf1(int n, float[] c, float[] ch, float[] wa, int[] ifac){
    int i, k1, l1, l2;
    int na, kh, nf;
    int ip, iw, ido, idl1, ix2, ix3;

    nf=ifac[1];
    na=1;
    l2=n;
    iw=n;

    for(k1=0; k1<nf; k1++){
      kh=nf-k1;
      ip=ifac[kh+1];
      l1=l2/ip;
      ido=n/l2;
      idl1=ido*l1;
      iw-=(ip-1)*ido;
      na=1-na;

      int state=100;
      loop: while(true){
        switch(state){
          case 100:
            if(ip!=4){
              state=102;
              break;
            }

            ix2=iw+ido;
            ix3=ix2+ido;
            if(na!=0)
              dradf4(ido, l1, ch, c, wa, iw-1, wa, ix2-1, wa, ix3-1);
            else
              dradf4(ido, l1, c, ch, wa, iw-1, wa, ix2-1, wa, ix3-1);
            state=110;
            break;
          case 102:
            if(ip!=2){
              state=104;
              break;
            }
            if(na!=0){
              state=103;
              break;
            }
            dradf2(ido, l1, c, ch, wa, iw-1);
            state=110;
            break;
          case 103:
            dradf2(ido, l1, ch, c, wa, iw-1);
          case 104:
            if(ido==1)
              na=1-na;
            if(na!=0){
              state=109;
              break;
            }
            dradfg(ido, ip, l1, idl1, c, c, c, ch, ch, wa, iw-1);
            na=1;
            state=110;
            break;
          case 109:
            dradfg(ido, ip, l1, idl1, ch, ch, ch, c, c, wa, iw-1);
            na=0;
          case 110:
            l2=l1;
            break loop;
        }
      }
    }
    if(na==1)
      return;
    for(i=0; i<n; i++)
      c[i]=ch[i];
  }

  static void dradb2(int ido, int l1, float[] cc, float[] ch, float[] wa1,
      int index){
    int i, k, t0, t1, t2, t3, t4, t5, t6;
    float ti2, tr2;

    t0=l1*ido;

    t1=0;
    t2=0;
    t3=(ido<<1)-1;
    for(k=0; k<l1; k++){
      ch[t1]=cc[t2]+cc[t3+t2];
      ch[t1+t0]=cc[t2]-cc[t3+t2];
      t2=(t1+=ido)<<1;
    }

    if(ido<2)
      return;
    if(ido!=2){
      t1=0;
      t2=0;
      for(k=0; k<l1; k++){
        t3=t1;
        t5=(t4=t2)+(ido<<1);
        t6=t0+t1;
        for(i=2; i<ido; i+=2){
          t3+=2;
          t4+=2;
          t5-=2;
          t6+=2;
          ch[t3-1]=cc[t4-1]+cc[t5-1];
          tr2=cc[t4-1]-cc[t5-1];
          ch[t3]=cc[t4]-cc[t5];
          ti2=cc[t4]+cc[t5];
          ch[t6-1]=wa1[index+i-2]*tr2-wa1[index+i-1]*ti2;
          ch[t6]=wa1[index+i-2]*ti2+wa1[index+i-1]*tr2;
        }
        t2=(t1+=ido)<<1;
      }
      if((ido%2)==1)
        return;
    }

    t1=ido-1;
    t2=ido-1;
    for(k=0; k<l1; k++){
      ch[t1]=cc[t2]+cc[t2];
      ch[t1+t0]=-(cc[t2+1]+cc[t2+1]);
      t1+=ido;
      t2+=ido<<1;
    }
  }

  static void dradb3(int ido, int l1, float[] cc, float[] ch, float[] wa1,
      int index1, float[] wa2, int index2){
    int i, k, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    float ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
    t0=l1*ido;

    t1=0;
    t2=t0<<1;
    t3=ido<<1;
    t4=ido+(ido<<1);
    t5=0;
    for(k=0; k<l1; k++){
      tr2=cc[t3-1]+cc[t3-1];
      cr2=cc[t5]+(taur*tr2);
      ch[t1]=cc[t5]+tr2;
      ci3=taui*(cc[t3]+cc[t3]);
      ch[t1+t0]=cr2-ci3;
      ch[t1+t2]=cr2+ci3;
      t1+=ido;
      t3+=t4;
      t5+=t4;
    }

    if(ido==1)
      return;

    t1=0;
    t3=ido<<1;
    for(k=0; k<l1; k++){
      t7=t1+(t1<<1);
      t6=(t5=t7+t3);
      t8=t1;
      t10=(t9=t1+t0)+t0;

      for(i=2; i<ido; i+=2){
        t5+=2;
        t6-=2;
        t7+=2;
        t8+=2;
        t9+=2;
        t10+=2;
        tr2=cc[t5-1]+cc[t6-1];
        cr2=cc[t7-1]+(taur*tr2);
        ch[t8-1]=cc[t7-1]+tr2;
        ti2=cc[t5]-cc[t6];
        ci2=cc[t7]+(taur*ti2);
        ch[t8]=cc[t7]+ti2;
        cr3=taui*(cc[t5-1]-cc[t6-1]);
        ci3=taui*(cc[t5]+cc[t6]);
        dr2=cr2-ci3;
        dr3=cr2+ci3;
        di2=ci2+cr3;
        di3=ci2-cr3;
        ch[t9-1]=wa1[index1+i-2]*dr2-wa1[index1+i-1]*di2;
        ch[t9]=wa1[index1+i-2]*di2+wa1[index1+i-1]*dr2;
        ch[t10-1]=wa2[index2+i-2]*dr3-wa2[index2+i-1]*di3;
        ch[t10]=wa2[index2+i-2]*di3+wa2[index2+i-1]*dr3;
      }
      t1+=ido;
    }
  }

  static void dradb4(int ido, int l1, float[] cc, float[] ch, float[] wa1,
      int index1, float[] wa2, int index2, float[] wa3, int index3){
    int i, k, t0, t1, t2, t3, t4, t5, t6, t7, t8;
    float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
    t0=l1*ido;

    t1=0;
    t2=ido<<2;
    t3=0;
    t6=ido<<1;
    for(k=0; k<l1; k++){
      t4=t3+t6;
      t5=t1;
      tr3=cc[t4-1]+cc[t4-1];
      tr4=cc[t4]+cc[t4];
      tr1=cc[t3]-cc[(t4+=t6)-1];
      tr2=cc[t3]+cc[t4-1];
      ch[t5]=tr2+tr3;
      ch[t5+=t0]=tr1-tr4;
      ch[t5+=t0]=tr2-tr3;
      ch[t5+=t0]=tr1+tr4;
      t1+=ido;
      t3+=t2;
    }

    if(ido<2)
      return;
    if(ido!=2){
      t1=0;
      for(k=0; k<l1; k++){
        t5=(t4=(t3=(t2=t1<<2)+t6))+t6;
        t7=t1;
        for(i=2; i<ido; i+=2){
          t2+=2;
          t3+=2;
          t4-=2;
          t5-=2;
          t7+=2;
          ti1=cc[t2]+cc[t5];
          ti2=cc[t2]-cc[t5];
          ti3=cc[t3]-cc[t4];
          tr4=cc[t3]+cc[t4];
          tr1=cc[t2-1]-cc[t5-1];
          tr2=cc[t2-1]+cc[t5-1];
          ti4=cc[t3-1]-cc[t4-1];
          tr3=cc[t3-1]+cc[t4-1];
          ch[t7-1]=tr2+tr3;
          cr3=tr2-tr3;
          ch[t7]=ti2+ti3;
          ci3=ti2-ti3;
          cr2=tr1-tr4;
          cr4=tr1+tr4;
          ci2=ti1+ti4;
          ci4=ti1-ti4;

          ch[(t8=t7+t0)-1]=wa1[index1+i-2]*cr2-wa1[index1+i-1]*ci2;
          ch[t8]=wa1[index1+i-2]*ci2+wa1[index1+i-1]*cr2;
          ch[(t8+=t0)-1]=wa2[index2+i-2]*cr3-wa2[index2+i-1]*ci3;
          ch[t8]=wa2[index2+i-2]*ci3+wa2[index2+i-1]*cr3;
          ch[(t8+=t0)-1]=wa3[index3+i-2]*cr4-wa3[index3+i-1]*ci4;
          ch[t8]=wa3[index3+i-2]*ci4+wa3[index3+i-1]*cr4;
        }
        t1+=ido;
      }
      if(ido%2==1)
        return;
    }

    t1=ido;
    t2=ido<<2;
    t3=ido-1;
    t4=ido+(ido<<1);
    for(k=0; k<l1; k++){
      t5=t3;
      ti1=cc[t1]+cc[t4];
      ti2=cc[t4]-cc[t1];
      tr1=cc[t1-1]-cc[t4-1];
      tr2=cc[t1-1]+cc[t4-1];
      ch[t5]=tr2+tr2;
      ch[t5+=t0]=sqrt2*(tr1-ti1);
      ch[t5+=t0]=ti2+ti2;
      ch[t5+=t0]=-sqrt2*(tr1+ti1);

      t3+=ido;
      t1+=t2;
      t4+=t2;
    }
  }

  static void dradbg(int ido, int ip, int l1, int idl1, float[] cc, float[] c1,
      float[] c2, float[] ch, float[] ch2, float[] wa, int index){

    int idij, ipph=0, i, j, k, l, ik, is, t0=0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10=0, t11, t12;
    float dc2, ai1, ai2, ar1, ar2, ds2;
    int nbd=0;
    float dcp=0, arg, dsp=0, ar1h, ar2h;
    int ipp2=0;

    int state=100;

    loop: while(true){
      switch(state){
        case 100:
          t10=ip*ido;
          t0=l1*ido;
          arg=tpi/(float)ip;
          dcp=(float)Math.cos(arg);
          dsp=(float)Math.sin(arg);
          nbd=(ido-1)>>>1;
          ipp2=ip;
          ipph=(ip+1)>>>1;
          if(ido<l1){
            state=103;
            break;
          }
          t1=0;
          t2=0;
          for(k=0; k<l1; k++){
            t3=t1;
            t4=t2;
            for(i=0; i<ido; i++){
              ch[t3]=cc[t4];
              t3++;
              t4++;
            }
            t1+=ido;
            t2+=t10;
          }
          state=106;
          break;
        case 103:
          t1=0;
          for(i=0; i<ido; i++){
            t2=t1;
            t3=t1;
            for(k=0; k<l1; k++){
              ch[t2]=cc[t3];
              t2+=ido;
              t3+=t10;
            }
            t1++;
          }
        case 106:
          t1=0;
          t2=ipp2*t0;
          t7=(t5=ido<<1);
          for(j=1; j<ipph; j++){
            t1+=t0;
            t2-=t0;
            t3=t1;
            t4=t2;
            t6=t5;
            for(k=0; k<l1; k++){
              ch[t3]=cc[t6-1]+cc[t6-1];
              ch[t4]=cc[t6]+cc[t6];
              t3+=ido;
              t4+=ido;
              t6+=t10;
            }
            t5+=t7;
          }
          if(ido==1){
            state=116;
            break;
          }
          if(nbd<l1){
            state=112;
            break;
          }

          t1=0;
          t2=ipp2*t0;
          t7=0;
          for(j=1; j<ipph; j++){
            t1+=t0;
            t2-=t0;
            t3=t1;
            t4=t2;

            t7+=(ido<<1);
            t8=t7;
            for(k=0; k<l1; k++){
              t5=t3;
              t6=t4;
              t9=t8;
              t11=t8;
              for(i=2; i<ido; i+=2){
                t5+=2;
                t6+=2;
                t9+=2;
                t11-=2;
                ch[t5-1]=cc[t9-1]+cc[t11-1];
                ch[t6-1]=cc[t9-1]-cc[t11-1];
                ch[t5]=cc[t9]-cc[t11];
                ch[t6]=cc[t9]+cc[t11];
              }
              t3+=ido;
              t4+=ido;
              t8+=t10;
            }
          }
          state=116;
          break;
        case 112:
          t1=0;
          t2=ipp2*t0;
          t7=0;
          for(j=1; j<ipph; j++){
            t1+=t0;
            t2-=t0;
            t3=t1;
            t4=t2;
            t7+=(ido<<1);
            t8=t7;
            t9=t7;
            for(i=2; i<ido; i+=2){
              t3+=2;
              t4+=2;
              t8+=2;
              t9-=2;
              t5=t3;
              t6=t4;
              t11=t8;
              t12=t9;
              for(k=0; k<l1; k++){
                ch[t5-1]=cc[t11-1]+cc[t12-1];
                ch[t6-1]=cc[t11-1]-cc[t12-1];
                ch[t5]=cc[t11]-cc[t12];
                ch[t6]=cc[t11]+cc[t12];
                t5+=ido;
                t6+=ido;
                t11+=t10;
                t12+=t10;
              }
            }
          }
        case 116:
          ar1=1.f;
          ai1=0.f;
          t1=0;
          t9=(t2=ipp2*idl1);
          t3=(ip-1)*idl1;
          for(l=1; l<ipph; l++){
            t1+=idl1;
            t2-=idl1;

            ar1h=dcp*ar1-dsp*ai1;
            ai1=dcp*ai1+dsp*ar1;
            ar1=ar1h;
            t4=t1;
            t5=t2;
            t6=0;
            t7=idl1;
            t8=t3;
            for(ik=0; ik<idl1; ik++){
              c2[t4++]=ch2[t6++]+ar1*ch2[t7++];
              c2[t5++]=ai1*ch2[t8++];
            }
            dc2=ar1;
            ds2=ai1;
            ar2=ar1;
            ai2=ai1;

            t6=idl1;
            t7=t9-idl1;
            for(j=2; j<ipph; j++){
              t6+=idl1;
              t7-=idl1;
              ar2h=dc2*ar2-ds2*ai2;
              ai2=dc2*ai2+ds2*ar2;
              ar2=ar2h;
              t4=t1;
              t5=t2;
              t11=t6;
              t12=t7;
              for(ik=0; ik<idl1; ik++){
                c2[t4++]+=ar2*ch2[t11++];
                c2[t5++]+=ai2*ch2[t12++];
              }
            }
          }

          t1=0;
          for(j=1; j<ipph; j++){
            t1+=idl1;
            t2=t1;
            for(ik=0; ik<idl1; ik++)
              ch2[ik]+=ch2[t2++];
          }

          t1=0;
          t2=ipp2*t0;
          for(j=1; j<ipph; j++){
            t1+=t0;
            t2-=t0;
            t3=t1;
            t4=t2;
            for(k=0; k<l1; k++){
              ch[t3]=c1[t3]-c1[t4];
              ch[t4]=c1[t3]+c1[t4];
              t3+=ido;
              t4+=ido;
            }
          }

          if(ido==1){
            state=132;
            break;
          }
          if(nbd<l1){
            state=128;
            break;
          }

          t1=0;
          t2=ipp2*t0;
          for(j=1; j<ipph; j++){
            t1+=t0;
            t2-=t0;
            t3=t1;
            t4=t2;
            for(k=0; k<l1; k++){
              t5=t3;
              t6=t4;
              for(i=2; i<ido; i+=2){
                t5+=2;
                t6+=2;
                ch[t5-1]=c1[t5-1]-c1[t6];
                ch[t6-1]=c1[t5-1]+c1[t6];
                ch[t5]=c1[t5]+c1[t6-1];
                ch[t6]=c1[t5]-c1[t6-1];
              }
              t3+=ido;
              t4+=ido;
            }
          }
          state=132;
          break;
        case 128:
          t1=0;
          t2=ipp2*t0;
          for(j=1; j<ipph; j++){
            t1+=t0;
            t2-=t0;
            t3=t1;
            t4=t2;
            for(i=2; i<ido; i+=2){
              t3+=2;
              t4+=2;
              t5=t3;
              t6=t4;
              for(k=0; k<l1; k++){
                ch[t5-1]=c1[t5-1]-c1[t6];
                ch[t6-1]=c1[t5-1]+c1[t6];
                ch[t5]=c1[t5]+c1[t6-1];
                ch[t6]=c1[t5]-c1[t6-1];
                t5+=ido;
                t6+=ido;
              }
            }
          }
        case 132:
          if(ido==1)
            return;

          for(ik=0; ik<idl1; ik++)
            c2[ik]=ch2[ik];

          t1=0;
          for(j=1; j<ip; j++){
            t2=(t1+=t0);
            for(k=0; k<l1; k++){
              c1[t2]=ch[t2];
              t2+=ido;
            }
          }

          if(nbd>l1){
            state=139;
            break;
          }

          is=-ido-1;
          t1=0;
          for(j=1; j<ip; j++){
            is+=ido;
            t1+=t0;
            idij=is;
            t2=t1;
            for(i=2; i<ido; i+=2){
              t2+=2;
              idij+=2;
              t3=t2;
              for(k=0; k<l1; k++){
                c1[t3-1]=wa[index+idij-1]*ch[t3-1]-wa[index+idij]*ch[t3];
                c1[t3]=wa[index+idij-1]*ch[t3]+wa[index+idij]*ch[t3-1];
                t3+=ido;
              }
            }
          }
          return;

        case 139:
          is=-ido-1;
          t1=0;
          for(j=1; j<ip; j++){
            is+=ido;
            t1+=t0;
            t2=t1;
            for(k=0; k<l1; k++){
              idij=is;
              t3=t2;
              for(i=2; i<ido; i+=2){
                idij+=2;
                t3+=2;
                c1[t3-1]=wa[index+idij-1]*ch[t3-1]-wa[index+idij]*ch[t3];
                c1[t3]=wa[index+idij-1]*ch[t3]+wa[index+idij]*ch[t3-1];
              }
              t2+=ido;
            }
          }
          break loop;
      }
    }
  }

  static void drftb1(int n, float[] c, float[] ch, float[] wa, int index,
      int[] ifac){
    int i, k1, l1, l2=0;
    int na;
    int nf, ip=0, iw, ix2, ix3, ido=0, idl1=0;

    nf=ifac[1];
    na=0;
    l1=1;
    iw=1;

    for(k1=0; k1<nf; k1++){
      int state=100;
      loop: while(true){
        switch(state){
          case 100:
            ip=ifac[k1+2];
            l2=ip*l1;
            ido=n/l2;
            idl1=ido*l1;
            if(ip!=4){
              state=103;
              break;
            }
            ix2=iw+ido;
            ix3=ix2+ido;

            if(na!=0)
              dradb4(ido, l1, ch, c, wa, index+iw-1, wa, index+ix2-1, wa, index
                  +ix3-1);
            else
              dradb4(ido, l1, c, ch, wa, index+iw-1, wa, index+ix2-1, wa, index
                  +ix3-1);
            na=1-na;
            state=115;
            break;
          case 103:
            if(ip!=2){
              state=106;
              break;
            }

            if(na!=0)
              dradb2(ido, l1, ch, c, wa, index+iw-1);
            else
              dradb2(ido, l1, c, ch, wa, index+iw-1);
            na=1-na;
            state=115;
            break;

          case 106:
            if(ip!=3){
              state=109;
              break;
            }

            ix2=iw+ido;
            if(na!=0)
              dradb3(ido, l1, ch, c, wa, index+iw-1, wa, index+ix2-1);
            else
              dradb3(ido, l1, c, ch, wa, index+iw-1, wa, index+ix2-1);
            na=1-na;
            state=115;
            break;
          case 109:
            if(na!=0)
              dradbg(ido, ip, l1, idl1, ch, ch, ch, c, c, wa, index+iw-1);
            else
              dradbg(ido, ip, l1, idl1, c, c, c, ch, ch, wa, index+iw-1);
            if(ido==1)
              na=1-na;

          case 115:
            l1=l2;
            iw+=(ip-1)*ido;
            break loop;
        }
      }
    }
    if(na==0)
      return;
    for(i=0; i<n; i++)
      c[i]=ch[i];
  }
}
